﻿using System;
using System.Globalization;

namespace Notoric.ViewModel.Elements.CWNotation
{
    /// <summary>
    /// Adapts a <see cref="Model.Elements.CWNotation.KeySignatureSign"/> instance to a Windows Presentation Foundation view.
    /// </summary>
    public class KeySignatureSign : ViewModelElement
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="KeySignatureSign"/> instance.
        /// </summary>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="KeySignature"/>
        /// </para>
        /// <para>
        /// The element that directly owns this element.
        /// </para>
        /// </param>
        /// <param name="adaptedElement">
        /// <para>
        /// Type: <see cref="Model.Elements.CWNotation.KeySignatureSign"/>
        /// </para>
        /// <para>
        /// The adapted model element instance.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="adaptedElement"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="NullReferenceException">
        /// <paramref name="owner"/> is <see langword="null"/>.
        /// The values of the <see cref="ViewModelElement.UndoStack"/> and <see cref="ViewModelElement.RedoStack"/> properties
        /// are passed directly to the base class (<see cref="ViewModelElement"/>) constructor. Thus, there is not
        /// an occasion to react with a more appropriate exception.
        /// </exception>
        public KeySignatureSign(KeySignature owner, Model.Elements.CWNotation.KeySignatureSign adaptedElement)
            : base(adaptedElement, owner, owner.UndoStack, owner.RedoStack)
        {
            RegisterToOwnerPropertyChanged<KeySignature>();
        }

        #endregion

        #region ViewModelElement Members

        /// <inheritdoc/>
        public override string ElementNameKey
        {
            get { return elementNameKey; }
        }

        #endregion

        #region Event Handlers

        /// <inheritdoc/>
        protected override bool AdaptedElement_PropertyChanged(global::System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "StaffPosition")
            {
                RaisePropertyChanged("VerticalPosition");
                return false;
            }
            return base.AdaptedElement_PropertyChanged(e);
        }

        /// <inheritdoc/>
        protected override void Owner_PropertyChanged(ViewModelElement owner, global::System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "VerticalPosition")
                RaisePropertyChanged("VerticalPosition");
            else if (e.PropertyName == "Position")
                RaisePropertyChanged("Position");
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets the type of the accidental represented by this sign.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="CWNotation.AccidentalType"/>
        /// </para>
        /// <para>
        /// The type of the accidental represented by this sign.
        /// </para>
        /// </value>
        public AccidentalType AccidentalType
        {
            get 
            {
                var modelType = ((Model.Elements.CWNotation.KeySignatureSign)AdaptedElement).AccidentalType;

                return (CWNotation.AccidentalType)Enum.Parse(typeof(CWNotation.AccidentalType), modelType.ToString());
            }
        }

        /// <summary>
        /// Gets the position of the sign.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Double"/>
        /// </para>
        /// <para>
        /// The distance (in device independent pixels) of the sign's left edge
        /// from the section's left edge.
        /// </para>
        /// </value>
        public double Position
        {
            get 
            {
                return FindOwner<KeySignature>().Position + (double)LengthConverter.Convert(
                    ((Model.Elements.CWNotation.KeySignatureSign)AdaptedElement).Position,
                    typeof(double),
                    null,
                    CultureInfo.CurrentCulture
                    );
                }
        }

        /// <summary>
        /// Gets the vertical position of the sign.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Double"/>
        /// </para>
        /// <para>
        /// The distance (in device independent pixels) of the sign from the section's top edge.
        /// </para>
        /// </value>
        public double VerticalPosition
        {
            get
            {
                return FindOwner<Staff>().Bottom - ((Model.Elements.CWNotation.KeySignatureSign)AdaptedElement).StaffPosition * (FindOwner<Staff>().SpaceSize / 2);
            }
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds a user-friendly name of this element.
        /// </summary>
        private const string elementNameKey = "ViewModel.ElementNames.KeySignatureSign";
        
        #endregion
    }
}
